#include "drv_rtc.h"
#include "delay.h"
#include "stdio.h"
#include <stdlib.h>

static uint64_t RTCnum=0;

//判断是否是闰年函数
//月份   1  2  3  4  5  6  7  8  9  10 11 12
//闰年   31 29 31 30 31 30 31 31 30 31 30 31
//非闰年 31 28 31 30 31 30 31 31 30 31 30 31
//输入:年份
//输出:该年份是不是闰年.1,是.0,不是
uint8_t Is_Leap_Year(uint16_t year){			  
	if(year%4==0){ //必须能被4整除
		if(year%100==0){ 
			if(year%400==0){
				return 1;//如果以00结尾,还要能被400整除 
			}else{
				return 0;   
			}
		}else{
			return 1;   
		}
	}else 
		return 0;	
}

uint8_t const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表	  
//平年的月份日期表
const uint8_t mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};

//获取时间戳,从1970年开始到现在的秒数
uint64_t getTimeStamp(void){
	uint16_t t;
	uint64_t seccount=0;
	unsigned char hour,min,sec;
	unsigned short year;
	unsigned char mon;
	uint32_t day;
	int tempYear = 1970;
	unsigned int tempDay = 0;
	unsigned int tempMon = 0;
	stc_rtc_date_time_t stcRtcDateTimeCfg;
	MEM_ZERO_STRUCT(stcRtcDateTimeCfg);
	RTC_GetDateTime(RtcDataFormatDec, &stcRtcDateTimeCfg);
	year = 2000 + stcRtcDateTimeCfg.u8Year;
	mon = stcRtcDateTimeCfg.u8Month;
	day = stcRtcDateTimeCfg.u8Day;
	hour = stcRtcDateTimeCfg.u8Hour;
	min = stcRtcDateTimeCfg.u8Minute;
	sec = stcRtcDateTimeCfg.u8Second;
	for(t=1970;t<year;t++){	//把所有年份的秒钟相加
		if(Is_Leap_Year(t)){
			seccount+=31622400;//闰年的秒钟数
		}else{
			seccount+=31536000;			  //平年的秒钟数
		}
	}
	mon-=1;
	for(t=0;t<mon;t++){	   //把前面月份的秒钟数相加
		seccount+=(uint32_t)mon_table[t]*86400;//月份秒钟数相加
		if(Is_Leap_Year(year)&&t==1){
			seccount+=86400;//闰年2月份增加一天的秒钟数	   
		}
	}
	seccount+=(uint32_t)(day-1)*86400;//把前面日期的秒钟数相加 
	seccount+=(uint32_t)hour*3600;//小时秒钟数
    seccount+=(uint32_t)min*60;	 //分钟秒钟数
	seccount+=sec;//最后的秒钟加上去
	seccount -= 8*3600;
	day = seccount/86400;
	
	return seccount;	    
}

//通过时间戳设定时间
//返回值:0,成功;其他:错误代码.
void setLocalTime(uint64_t timeStamp){
	uint32_t temp=0;
	uint16_t temp1=0;	
	uint16_t year = 0;
	uint16_t month =0;
	uint16_t date = 0;
	uint32_t hour = 0;
	uint32_t min = 0;
	uint32_t sec = 0;  	 
	timeStamp += 8*3600;
 	temp=timeStamp/86400;   //得到天数(秒钟数对应的)	  
	temp1=1970;	//从1970年开始
	while(temp>=365){				 
		if(Is_Leap_Year(temp1)){//是闰年
			if(temp>=366){
				temp-=366;//闰年的秒钟数
			}else{
				temp1++;break;
			}  
		}else{
			temp-=365;	  //平年
		}
		temp1++;  
	}   
	year=temp1;//得到年份
	temp1=0;
	while(temp>=28){//超过了一个月
		if(Is_Leap_Year(year)&&temp1==1){//当年是不是闰年/2月份
			if(temp>=29){
				temp-=29;//闰年的秒钟数
			}else{
				break; 
			}
		}else{ 
			if(temp>=mon_table[temp1]){
				temp-=mon_table[temp1];//平年
			}else{ 
				break;
			}
		}
		temp1++;  
	}
	month=temp1+1;	//得到月份
	date=temp+1;  	//得到日期 
	temp=timeStamp%86400;   //得到秒钟数   	   
	hour=temp/3600;     	//小时
	min=(temp%3600)/60; 	//分钟	
	sec=(temp%3600)%60; 	//秒钟 
	
	set_time(year%100,month,date,hour,min,sec);
}

void set_time(uint8_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t second){
	stc_rtc_date_time_t stcRtcDateTimeCfg;
	MEM_ZERO_STRUCT(stcRtcDateTimeCfg);
	stcRtcDateTimeCfg.u8Year = year;
	stcRtcDateTimeCfg.u8Month = month;
	stcRtcDateTimeCfg.u8Day = day;
	stcRtcDateTimeCfg.u8Hour = hour;
	stcRtcDateTimeCfg.u8Minute = minute;
	stcRtcDateTimeCfg.u8Second = second;
	if (RTC_SetDateTime(RtcDataFormatDec, &stcRtcDateTimeCfg, Enable, Enable) != Ok){
		printf("set time failed!\r\n");
	}
}

void getRtcTimeHex(char *timeHex){
	stc_rtc_date_time_t stcRtcDateTimeCfg;
	MEM_ZERO_STRUCT(stcRtcDateTimeCfg);
	RTC_GetDateTime(RtcDataFormatDec, &stcRtcDateTimeCfg);
	timeHex[0] = stcRtcDateTimeCfg.u8Year;
	timeHex[1] = stcRtcDateTimeCfg.u8Month;
	timeHex[2] = stcRtcDateTimeCfg.u8Day;
	timeHex[3] = stcRtcDateTimeCfg.u8Hour;
	timeHex[4] = stcRtcDateTimeCfg.u8Minute;
	timeHex[5] = stcRtcDateTimeCfg.u8Second;
}

void getRtcTimeHexModbus(uint16_t *timeHex){
	stc_rtc_date_time_t stcRtcDateTimeCfg;
	MEM_ZERO_STRUCT(stcRtcDateTimeCfg);
	RTC_GetDateTime(RtcDataFormatDec, &stcRtcDateTimeCfg);
	uint16_t Year=0;
	uint16_t Day=0;
	uint16_t Minute=0;
	uint16_t YearMonth=0;
	uint16_t DayHour=0;
	uint16_t MinuteSecond=0;
	
	Year=(stcRtcDateTimeCfg.u8Year<<8) & 0xff00;
	YearMonth = stcRtcDateTimeCfg.u8Month | Year;
	timeHex[0] = YearMonth;
	
	Day=(stcRtcDateTimeCfg.u8Day<<8) & 0xff00;
	DayHour=stcRtcDateTimeCfg.u8Hour | Day;
	timeHex[1] = DayHour;
	
	Minute=(stcRtcDateTimeCfg.u8Minute<<8) & 0xff00;
	MinuteSecond=stcRtcDateTimeCfg.u8Second | Minute;
	timeHex[2] = MinuteSecond;
}

void getBcdTime(char *bcdTime){
	char time[8] = {0};
	getRtcTimeHex(time);
	bcdTime[0] = time[0]/10*16 + time[0]%10;
	bcdTime[1] = time[1]/10*16 + time[1]%10;
	bcdTime[2] = time[2]/10*16 + time[2]%10;
	bcdTime[3] = time[3]/10*16 + time[3]%10;
	bcdTime[4] = time[4]/10*16 + time[4]%10;
	bcdTime[5] = time[5]/10*16 + time[5]%10;
}

void set_bcd_date_time(char *bcdTime){
	uint8_t currentYear = bcdTime[0]/16*10 + bcdTime[0]%16;
	uint8_t currentMonth = bcdTime[1]/16*10 + bcdTime[1]%16;
	uint8_t currentDay = bcdTime[2]/16*10 + bcdTime[2]%16;
	uint8_t currentHour = bcdTime[3]/16*10 + bcdTime[3]%16;
	uint8_t currentMinute = bcdTime[4]/16*10 + bcdTime[4]%16;
	uint8_t currentSecond = bcdTime[5]/16*10 + bcdTime[5]%16; 
	set_time(currentYear,currentMonth,currentDay,currentHour,currentMinute,currentSecond);
}

void set_hex_date_time(char *hexTime){
	set_time(hexTime[0],hexTime[1],hexTime[2],hexTime[3],hexTime[4],hexTime[5]);
}

void set_rtc_date_time(char *timeStr){
	stc_rtc_date_time_t stcRtcDateTimeCfg;
	/* configure structure initialization */
	MEM_ZERO_STRUCT(stcRtcDateTimeCfg);

	char valueStr[4] = {0};
	memset(valueStr,0,4);
	memcpy(valueStr,&timeStr[2],2);
	/* calendar configuration */
	stcRtcDateTimeCfg.u8Year = atoi(valueStr);
	memset(valueStr,0,4);
	memcpy(valueStr,&timeStr[4],2);
	stcRtcDateTimeCfg.u8Month = atoi(valueStr);
	memset(valueStr,0,4);
	memcpy(valueStr,&timeStr[6],2);
	stcRtcDateTimeCfg.u8Day = atoi(valueStr);
	stcRtcDateTimeCfg.u8Weekday = RtcWeekdayTuesday;
	memset(valueStr,0,4);
	memcpy(valueStr,&timeStr[8],2);
	stcRtcDateTimeCfg.u8Hour = atoi(valueStr);
	memset(valueStr,0,4);
	memcpy(valueStr,&timeStr[10],2);
	stcRtcDateTimeCfg.u8Minute = atoi(valueStr);
	memset(valueStr,0,4);
	memcpy(valueStr,&timeStr[12],2);
	stcRtcDateTimeCfg.u8Second = atoi(valueStr);
	if (RTC_SetDateTime(RtcDataFormatDec, &stcRtcDateTimeCfg, Enable, Enable) != Ok){
		printf("write calendar failed!\r\n");
	}
}

void RtcSetAlarmTime(uint16_t min){
	if(min <= 0){
		return;
	}
	//获取当前RTC时间
	stc_rtc_date_time_t rtcTime;
	MEM_ZERO_STRUCT(rtcTime);
	RTC_GetDateTime(RtcDataFormatDec, &rtcTime);	
	stc_rtc_alarm_time_t alarm_time;
	alarm_time.u8Weekday = rtcTime.u8Weekday;
	alarm_time.u8Hour = rtcTime.u8Hour;
	alarm_time.u8Minute = rtcTime.u8Minute;
	alarm_time.u8Minute += min%60;
	alarm_time.u8Hour += min/60;
	alarm_time.u8Weekday += alarm_time.u8Hour/24;
	alarm_time.u8Hour %= 24;
	alarm_time.u8Weekday%= 7;
	if(alarm_time.u8Minute > 59){//如果
		alarm_time.u8Minute = 0;
		alarm_time.u8Hour += 1;
	}
	if(alarm_time.u8Hour > 23){
		alarm_time.u8Hour = 0;
		alarm_time.u8Weekday += 1;
	}
	if(alarm_time.u8Weekday > 6){
		alarm_time.u8Weekday = 0;
	}
	alarm_time.u8Hour = DEC2BCD(alarm_time.u8Hour);
    alarm_time.u8Minute = DEC2BCD(alarm_time.u8Minute);
	alarm_time.u8Weekday = 1 << alarm_time.u8Weekday;
	RTC_SetAlarmTime(RtcDataFormatBcd,&alarm_time);
	RTC_AlarmCmd(Enable);
}

void RtcAlarmWakeEnable(uint8_t enable){
	enable == 1?RTC_AlarmCmd(Enable):RTC_AlarmCmd(Disable);;
}

static RtcIntCallBack rtcCallBackFunc = NULL;

void RtcAlarm_IrqCallback(void){
	RTC_ClearAlarmFlag();
	if(rtcCallBackFunc != NULL){
		rtcCallBackFunc();
	}
}

void RtcSetCallBack(RtcIntCallBack callBack)
{
	rtcCallBackFunc = callBack;
}


static void RtcPeriod_IrqCallback(void)
{
	RTCnum++;
}

uint64_t batVolDiff_num(void)
{
	return RTCnum;
}


void Rtc_Config(void){
    stc_rtc_init_t stcRtcInit;
    stc_irq_regi_conf_t stcIrqRegiConf;
    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcRtcInit);
    MEM_ZERO_STRUCT(stcIrqRegiConf);
	/* Configuration rtc structure */
	stcRtcInit.enClkSource = RtcClkLrc;
	stcRtcInit.enPeriodInt = RtcPeriodIntOneSec;
	stcRtcInit.enTimeFormat = RtcTimeFormat24Hour;
	stcRtcInit.enCompenWay = RtcOutputCompenDistributed;
	stcRtcInit.enCompenEn = Disable;
	stcRtcInit.u16CompenVal = 0u;
	RTC_Init(&stcRtcInit);
	
	
	/* Configure interrupt of rtc period */
	stcIrqRegiConf.enIntSrc = INT_RTC_PRD;
	stcIrqRegiConf.enIRQn = Int008_IRQn;
	stcIrqRegiConf.pfnCallback = &RtcPeriod_IrqCallback;
	enIrqRegistration(&stcIrqRegiConf);
	NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
	NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
	NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
		
	/* Configure interrupt of rtc alarm */
	stcIrqRegiConf.enIntSrc = INT_RTC_ALM;
	stcIrqRegiConf.enIRQn = Int009_IRQn;
	stcIrqRegiConf.pfnCallback = &RtcAlarm_IrqCallback;
	enIrqRegistration(&stcIrqRegiConf);
	NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
	NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
	NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
	RTC_ClearAlarmFlag();	
	
	/* Enable period interrupt */
	RTC_IrqCmd(RtcIrqPeriod,Enable);
	RTC_IrqCmd(RtcIrqAlarm,Enable);
	/* Startup rtc count */
	enIntWakeupEnable(RtcAlarmWU);
	
	RTC_Cmd(Enable);
}
